function softBits = WiSiL_Encoder_turboDecoder(bitsRxEncoded,encoder,ebN0)


% TURBODECODER - Performs the turbo decoding
%
%
% Syntax:
%
%     bitsRx = TurboEncoder(bitsRxEncoded,encoder,alpha,ebN0)
%     This function implements the turbo decoding.
%
%   Input parameters:
%     bitsRxEncoded : The bit sequence received at the output of the
%     modulator.
%     encoder : Struct containing the field encoder.tcPoly, which is the
%     polynomial generator for the RSC encoder presents at Turbo Coding.
%
%   Output parameters:
%     bitsRx : The bit sequence decoded.
% 
% 
% The Turbo Decoding is performed according to the following steps:
%  1)The received message (bitsRxEncoded) is separated into three vectors
%    (Y1, Y2,Y3). Where Y1 is the soft output for the systematic bit; Y2 is the
%    soft output for the parity bit of the first RSC of the Turbo Encoder;
%    Y3 is the soft output for the parity bit of the second RSC of the Turbo Encoder (interleaved
%    sequence).
%  2) The mapped signal is passed through the SOVA (Soft Output Viterbi 
%     Algorithm) Iterative Decoder. (See scheme below).
%  3) At the output of the SOVA Iterative Decoder, be X = sign(L(u)), after
%     the last iteration is performed. 
%  4) Vector X is mapped into bits (-1,1) => (0,1), tailbits are discarded.
%      The resulting vector is the output of the Turbo Decoder (bitsRx).
%
%
% 
%    SOVA Iterative Decoder Scheme:
%                                     - - - - - - - - - - - - - - - -             
%                                     |    _ _ _                     |      
%               _ _ _ _ _ _  Lc(Y2)    - >|      |                   |      
% 	           |           |- - - - - - ->| SOVA |L(u')              |      
%              |           |           - >|      | _ _ _ _           |      
%              |           |          |   |_ _ _ |        |          |      
%              |           |Lc(Y1)    |                   |          |      
%              |           |- - - - ->|                (+)|          |      
% Y1   ------> |           |          |            (-)   _V_   (-)   |      
%              | Channel   |          |- - - - - - - -> | + | <------| Le2(u)     
%              |Reliability|          |                 |_ _|       _|_    
%              |           |          |    _ _      _ _   |        | D |   
%              |           |          |   | I |    | I |<-|        |_ _|   
% Y2   ------->|           |           -->|_ _|    |_ _|  Le1(u)     ^           
%              |           |                |        |               |     
%              | 4*a*Eb/No |                |        |         (-)  _|_ (+)  
%              |           |                |---------)----------->| + |<--|
%              |           |                |        |             |_ _|   |
%              |           |                |        |           (-) ^     |
% Y3   ------->|           |                |        |---------------|     |
%              |           |                |        |    _ _ _            |    
%              |           |                |        - ->|      | ---------               
%              |           |Lc(Y3)           - - - - - ->| SOVA |       _ _         
%              |_ _ _ _ _ _|- - -  - - - - - - - - - - ->|_ _ _ | ---->| D |-> L(u)         
%                                                              I[L(u)] |_ _|
%
%
%     LEGEND:  Lc(Yn) - Channel Reliability for the n-th input sequence.
%              Le1    - Extrinsic value for the first SOVA decoder.
%              Le2    - Extrinsic value for the second SOVA decoder. (Set
%                       to  be ZERO for first iteration). 
%             SOVA    - Soft Output Viterbi Algorithm Decoder
%              L(u')  - Reliability for the systematic at the ouput of the 
%                       first SOVA Decoder
%              L(u)   - Reliability for the systematic bit at the output of
%                       the seconde SOVA Decoder.
%               I     - Interleaver
%               D     - Deinterleaver
%              I[x]   - Interleaved version of sequence x.

% History:
% Rafhael Medeiros de Amorim ( rma.petit@gmail.com )
% August 2nd, 2008.

% Set Decoder Parameters
constraint = 4; %Constraint length 
feedback = encoder.TurboCoding.feedback;   %Feedback polynomial used at Turbo Coding
poly = encoder.TurboCoding.poly;          %Generator polynomials 
trellis = poly2trellis(constraint,poly,feedback); % Trellis
iter = encoder.TurboCoding.iter;           %Number of decoding iterations

WiSiL_Encoder_interleaverTable; % Interleaver table (36.212) - Used to calculate the interleaved sequence
                    % to the second convolutiona encoder
Ki = length(bitsRxEncoded)-constraint; % Ki index - See 36.212 for more information.
index = find (K == Ki); % Find Ki at interleaver table

%Dealing with null values (filler bits) - See (36.212) for more information
    auxiliar = isnan(bitsRxEncoded);
    temp = find(auxiliar == 1);
    temp2 = length(temp);
    bitsRxEncoded(temp) = 0;
%--             ---                    -- 

%-- Interleaved Sequence  --
    alpha(1,:) = mod((1:Ki)*f1(index)+(1:Ki).^2*f2(index),Ki);
    alpha(1,:) = alpha+1;
%--        ---            --

 

%Other Parameters
ebN0Lin = 10^(ebN0/10);       %Convert ebN0 from dB unit to linear scale.
alpha = [alpha (length(alpha)+1:length(alpha)+constraint)]; %Tailbits are not interleaved


%Y1, Y2 and Y3.
Y(1,:) = bitsRxEncoded(1:3:end); % Systematic Bit Estimation
Y(2,:) = bitsRxEncoded(2:3:end); % 1st Parity Bit Estimation
Y(3,:) = bitsRxEncoded(3:3:end); % 2nd Pariti Bit Estimation

% Channel Reliability
Lc = Y*4*ebN0Lin;

%Initialization of extrinsic information of the second decoder.
Le2 = zeros(size(Lc,2),1);

%Input sequence for first decoder (LcY1,LcY2).
input1 = reshape(Lc(1:2,:),1,[]);

%Input sequence for second decoder (LcI[Y1],LcY3)
input2(1,:) = Lc(1,alpha);
input2(2,:) = Lc(3,:);

[~,x] = sort(alpha);

if encoder.TurboCoding.C_core

%----                      If C - MEX FUNCTION is used                 ----

    %Set MEX Function Parameters 
    numInputs = log2(trellis.numInputSymbols); %Number of Inputs
    numOutputs = log2(trellis.numOutputSymbols); %Number of Outputs
    nextStates = trellis.nextStates; % Next State information
    nextOutputs = trellis.outputs; % State output
    numStates = trellis.numStates; % Number of States
    codeRate = numInputs/numOutputs;  %Code Rate
    Le2 = Le2'; 
    
    for n = 1:iter,

        %First Decoder.
        Lv= sovacore(input1,Le2,numInputs,numOutputs,numStates,nextStates,nextOutputs,codeRate); %L(u') output of the first decoder
        Le1 = Lv-Le2-Lc(1,:); %Extrinsic information for the first decoder.

        %Second Decoder
        ILe1 = Le1(alpha);      %ILe1 = Interleaved Extrinsic Information 1
        ILu = sovacore(input2,ILe1,numInputs,numOutputs,numStates,nextStates,nextOutputs,codeRate); %Interleaved output of the second decoder
        ILe2 = ILu-ILe1-Lc(1,alpha); %Interleaved Extrinsic Information 2


        %Deinterleaver for the Extrinsic Information 2
            Le2 = ILe2(x);

    end
     %Deinterleaver the output L(u)
     Lu = ILu(x);

else
    for n = 1:iter,

        %First Decoder.
        Lv= sovadec(input1,Le2,trellis); %L(u') output of the first decoder        
        %Lv= sovadec(input1,Le2,trellis,length(alpha)); %L(u') output of the first decoder        
        
        Le1 = Lv-Le2-Lc(1,:).'; %Extrinsic information for the first decoder.

        %Second Decoder
        ILe1 = Le1(alpha);      %ILe1 = Interleaved Extrinsic Information 1
        ILu = sovadec(input2,ILe1,trellis,length(alpha)); %Interleaved output of the second decoder
        ILe2 = ILu-ILe1-Lc(1,alpha).'; %Interleaved Extrinsic Information 2


        %Deinterleaver for the Extrinsic Information 2

            Le2 = ILe2(x);

    end
    %Deinterleaver the output L(u)
        Lu = ILu(x).';

end

    
%Decision:
softBits(1,:) = Lu(1,1:length(auxiliar)-(constraint)); %Discard
% tailBits.

softBits(1:temp2/3) = [];
